package model

import (
	"gitee.com/sansaniot/ssiot-core/sdk/model"

	"ssdevice/common/dto"
	"ssdevice/internal/rule/model/query"
)

type Processor struct {
	Id         string        `json:"id"`
	Name       string        `json:"name"`
	Type       string        `json:"type" `
	Script     string        `json:"script"`
	Next       string        `json:"next"`
	Previous   string        `json:"previous"`
	RuleId     string        `json:"ruleId"`
	Desc       string        `json:"desc"`
	Loc        string        `json:"loc"`
	CreateTime dto.LocalTime `json:"createTime"`
	UpdateTime dto.LocalTime `json:"updateTime"`
	model.Model
}

type processorCache map[string]interface{}

func (r *Processor) GetById(id string) error {
	err := r.Orm.Where(Processor{Id: id}).First(r).Error
	return err
}

func (r *Processor) GetOne(q *query.ProcessorGetReq) error {
	where := dto.MakeCondition(*q)
	err := r.FindOne(r, where)
	return err
}

// FindPage 获取处理器列表
func (r *Processor) FindPage(q *query.ProcessorGetReq) (result interface{}, count int64, err error) {
	list := make([]*Processor, 0)
	where := dto.MakeCondition(*q)

	err = r.Orm.Model(r).Scopes(
		where,
		dto.OrderDest("create_time", true, q.OrderBy),
		dto.Paginate(q.GetPageSize(), q.GetPageIndex()),
	).Find(&list).Limit(-1).Offset(-1).Count(&count).Error

	return list, count, nil
}

// findChainsByRule 按规则id获取处理器列表,并按照先后顺序存入切片
func (r *Processor) findChainsByRule(ruleId string) (result []processorCache) {
	list := make([]*Processor, 0)
	_ = r.Orm.Model(r).Where(Processor{RuleId: ruleId}).Find(&list).Error
	if len(list) == 0 {
		return nil
	}

	// 将processor存入以id为key的map
	processorMap := make(map[string]*Processor)
	for _, p := range list {
		processorMap[p.Id] = p
	}

	// 找到第一个节点
	orderList := make([]processorCache, 0)
	first := r.findFirstProcessor(list)

	cache := map[string]interface{}{
		"id":     first.Id,
		"type":   first.Type,
		"script": first.Script,
	}

	if first != nil {
		orderList = append(orderList, cache)
	}

	// 递归组成规则链
	orderList = r.findNextProcessor(first, processorMap, orderList)

	return orderList
}

func (r *Processor) findFirstProcessor(list []*Processor) (first *Processor) {
	for _, p := range list {
		if p.Previous == "no" {
			return p
		}
	}
	return nil
}

// 递归组成规则链
func (r *Processor) findNextProcessor(current *Processor, processorMap map[string]*Processor, orderList []processorCache) (result []processorCache) {
	if current == nil || current.Next == "no" || current.Next == "" {
		return orderList
	}

	next := processorMap[current.Next]
	cache := map[string]interface{}{
		"id":     next.Id,
		"type":   next.Type,
		"script": next.Script,
	}

	orderList = append(orderList, cache)
	r.findNextProcessor(next, processorMap, orderList)
	return orderList
}

func (r *Processor) AddProcessor() error {
	err := r.Add(r)
	return err
}

func (r *Processor) Modify(model interface{}) error {
	return r.Mod(model)
}

func (r *Processor) Remove() error {
	return r.Delete(r)
}

func (r *Processor) RemoveByRuleId() {
	_ = r.DeleteByConds(r, Processor{RuleId: r.RuleId})
}

func (r *Processor) TableName() string {
	return "sys_rule_processor"
}

func (r *Processor) GetId() interface{} {
	return r.Id
}
